//************************************************************************
/// <copyrigth>2024-2025 Corporation.All Rights Reserved</copyrigth>
/// <author>tangyingzhong</author>
/// <contact>tangyz114987@outlook.com</contact>
/// <version>v1.0.0</version>
/// <describe>
/// Cross-Platform crypto which containing aes/des
///</describe>
/// <date>2024/3/10</date>
///***********************************************************************
#ifndef CRYPTO_H
#define CRYPTO_H

#include <iostream>
#include <string>
#include "ModuleLoader/ModuleConfig.h"

namespace SystemTool
{
    enum CLASS_ITEM BlockType
    {
        BLK_AES_128 = 0,
        BLK_AES_256,
        BLK_DES,
        BLK_DES3
    };

    enum CLASS_ITEM CipherMode
    {
        CIPHER_STREAM_CIPHER = 0,
        CIPHER_ECB,
        CIPHER_CBC,
        CIPHER_CFB,
        CIPHER_OFB,
        CIPHER_CTR,
        CIPHER_GCM,
        CIPHER_CCM
    };

    enum CLASS_ITEM CipherDigestType
    {
        DT_MD5 = 0,
        DT_SHA1
    };

    enum CLASS_ITEM CipherResultType
    {
        RT_NONE = 0x00,
        RT_BASE64 = 0x01,
        RT_BINHEX = 0x02,
        RT_BASE64_NO_LF = 0x81,
        RT_BINHEX_NO_LF = 0x82
    };

    class CLASS_ITEM BCrypto
    {
    public:
        // Encrypt data
        static std::string Encrypt(std::string &strData,
                              std::string strPassPhrase,
                              std::string strSalt = "",
                              BlockType eBlockType = BLK_AES_256,
                              CipherMode eMode = CIPHER_CBC,
                              CipherDigestType eDigestType = DT_MD5,
                              CipherResultType eRTType = RT_BASE64);

        // Encrypt data
        static std::string EncryptByKV(std::string &strData,
                              std::string strKey = "",
                              std::string strIV = "",
                              BlockType eBlockType = BLK_AES_256,
                              CipherMode eMode = CIPHER_CBC,
                              CipherResultType eRTType = RT_BASE64);

        // Decrypt data
        static std::string Decrypt(std::string &strData,
                              std::string strPassPhrase,
                              std::string strSalt = "",
                              BlockType eBlockType = BLK_AES_256,
                              CipherMode eMode = CIPHER_CBC,
                              CipherDigestType eDigestType = DT_MD5,
                              CipherResultType eRTType = RT_BASE64);
        // Decrypt data
        static std::string DecryptByKV(std::string &strData,
                              std::string strKey = "",
                              std::string strIV = "",
                              BlockType eBlockType = BLK_AES_256,
                              CipherMode eMode = CIPHER_CBC,
                              CipherResultType eRTType = RT_BASE64);

        // Encryp the stream
        static void EncryptStream(std::istream &is,
                            std::ostream &os,
                            std::string strPassPhrase,
                            std::string strSalt = "",
                            BlockType eBlockType = BLK_AES_256,
                            CipherMode eMode = CIPHER_CBC,
                            CipherDigestType eDigestType = DT_MD5,
                            CipherResultType eRTType = RT_BASE64);

        // Encryp the stream
        static void EncryptStreamByKV(std::istream &is,
                            std::ostream &os,
                            std::string strKey = "",
                            std::string strIV = "",
                            BlockType eBlockType = BLK_AES_256,
                            CipherMode eMode = CIPHER_CBC,
                            CipherResultType eRTType = RT_BASE64);

        // Decrypt the stream
        static void Decrypt(std::istream &is,
                            std::ostream &os,
                            std::string strPassPhrase,
                            std::string strSalt = "",
                            BlockType eBlockType = BLK_AES_256,
                            CipherMode eMode = CIPHER_CBC,
                            CipherDigestType eDigestType = DT_MD5,
                            CipherResultType eRTType = RT_BASE64);

        // Decrypt the stream
        static void DecryptStream(std::istream &is,
                            std::ostream &os,
                            std::string strKey = "",
                            std::string strIV = "",
                            BlockType eBlockType = BLK_AES_256,
                            CipherMode eMode = CIPHER_CBC,
                            CipherResultType eRTType = RT_BASE64);
    };
}

#endif // CRYPTO_H
